//  函数式编程

if (process.argv.indexOf('high') !== -1) {
  /**
   * 高阶函数
   * 接受函数作为参数或返回一个函数的函数就是高阶函数。
   * */

  // 模拟实现 foeEach
  function forEach(array, callback) {
    for (let i = 0, len = array.length; i < len; i++) {
      callback(array[i])
    }
  }

  const arr = [1,2,54,68,7879,49]
  forEach(arr, (val) => {
    console.log('循环的值', val)
  })

  // 模拟实现 filter
  function filter (array, callback) {
    const r = []
    for (let i = 0, len = array.length; i < len; i++) {
      if (callback(array[i])) {
        r.push(array[i])
      }
    }

    return r
  }

  console.log(filter(arr, val => val > 50))

  // 模拟实现 once , 返回一个对传入的函数只执行一次的函数
  function once (fn) {
    let done = false
    return function () {
      if (!done) {
        done = true
        fn.apply(this, arguments)
      }
    }
  }

  const pay = once((money) => {
    console.log(`金额为：${money}`)
  })

  pay(20)
  pay(30)
  pay(40)

  // 模拟实现 map some every

  function map (array, fn) {
    const result = []
    for (value of array) {
      result.push(fn(value))
    }

    return result
  }

  console.log(map(arr, val => val * 2))

  function some (array, fn) {
    let result = false

    for (value of array) {
      result = fn(value)
      if (result) {
        break
      }
    }

    return result
  }

  console.log(some(arr, val => val > 8000))

  // 是否每一个都通过
  function every (array, fn) {
    let result = true

    for(value of array) {
      result = fn(value)
      if (!result) break
    }

    return result
  }

  console.log(every(arr, val => val >= 1))

}

if (process.argv.indexOf('lodash') !== -1) {
  // 模拟柯里化函数的实现
  function currie (fn) {
    const argnLen = fn.length
    return function run () {
      if (arguments.length < argnLen) {
        const argus = Array.prototype.slice.call(arguments)
        return function () {
          return run.apply(run, argus.concat(Array.prototype.slice.call(arguments)))
        }
      } else {
        return fn.apply(fn, arguments)
      }
    }
  }

  const total = currie((val1, val2, val3) => {
    return val1 + val2 + val3
  })

  console.log(total(12,23)(34))
  console.log(total(1)(2)(34))
  console.log(total(12,34,10))

  // 组合函数的模拟实现
  function compose () {
    const argus = Array.prototype.slice.call(arguments)

    return function (value) {
      let len = argus.length
      
      while (len--) {
        value = argus[len](value)
      }

      return value
    }
  }

  const reverse = array => array.reverse()
  const first = array => array[0]
  const double = val => val*2

  const fn = compose(double, first, reverse)

  console.log(fn([12,23,5,57,8]))
}
